#include "clientwindow.h"
#include "ui_clientwindow.h"

ClientWindow::ClientWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::ClientWindow)
{
    ui->setupUi(this);

    connect(ui->connectButton, SIGNAL(clicked()), this, SLOT(buttonConnexion_clicked()));
    connect(ui->sendButton, SIGNAL(clicked()), this, SLOT(buttonSend_cliked()));
    connect(ui->message, SIGNAL(returnPressed()), this, SLOT(messsage_enter_pressed()));

    socket = new QTcpSocket(this);
    connect(socket, SIGNAL(readyRead()), this, SLOT(dataReceived()));
    connect(socket, SIGNAL(connected()), this, SLOT(clientConnect()));
    connect(socket, SIGNAL(disconnected()), this, SLOT(clientDisconnect()));
    connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(errorSocket(QAbstractSocket::SocketError)));

    messageSize = 0;
}

ClientWindow::~ClientWindow()
{
    delete ui;
}

void ClientWindow::buttonConnexion_clicked()
{
    ui->display->setText(tr("Attempting connection to server..."));
    ui->connectButton->setEnabled(false);
    setWindowTitle(ui->nickname->text());

    socket->abort();
    //connect
    socket->connectToHost(ui->address->text(), ui->port->text().toInt());

    //send nickname
    QByteArray packet;
    QDataStream out(&packet, QIODevice::WriteOnly);
    //set up message
    QString messageToSend = tr("<strong>") + ui->nickname->text() + tr("</strong>");
    out << (quint16) 0;
    out << messageToSend;
    out.device()->seek(0);
    out << (quint16) (packet.size() - sizeof(quint16));
    socket->write(packet);
}

void ClientWindow::buttonSend_cliked()
{
    QByteArray packet;
    QDataStream out(&packet, QIODevice::WriteOnly);

    //set up message
    QString messageToSend = tr("<strong>") + ui->nickname->text() + tr("</strong>: ") + ui->message->text();

    out << (quint16) 0;
    out << messageToSend;
    out.device()->seek(0);
    out << (quint16) (packet.size() - sizeof(quint16));

    socket->write(packet);

    ui->message->clear(); //clear message box
    ui->message->setFocus(); //select message box
}

void ClientWindow::messsage_enter_pressed()
{
    buttonSend_cliked();
}

void ClientWindow::dataReceived()
{
    QDataStream in(socket);

    if (messageSize == 0)
    {
       if (socket->bytesAvailable() < (int)sizeof(quint16))
            return;

       in >> messageSize;
    }

    if (socket->bytesAvailable() < messageSize)
       return;


    // At this point the whole message can be received
    QString messageReceived;
    in >> messageReceived;

    // Display the message in chat
    ui->display->append(messageReceived);

    // Reset the message size for future messages
    messageSize = 0;
}

void ClientWindow::clientConnect()
{
    ui->display->append(tr("<em>Connection established!</em>"));
    //disable connection
    ui->port->setEnabled(false);
    ui->address->setEnabled(false);
    ui->nickname->setEnabled(false);
    ui->connectButton->setEnabled(false);
    //enable messages
    ui->message->setEnabled(true);
    ui->sendButton->setEnabled(true);
}

void ClientWindow::clientDisconnect()
{
    ui->display->append(tr("<em>Disconnected from server.</em>"));
    //disable messages
    ui->message->setEnabled(false);
    ui->nickname->setEnabled(false);
    ui->sendButton->setEnabled(false);
    //enable connection
    ui->port->setEnabled(true);
    ui->address->setEnabled(true);
    ui->connectButton->setEnabled(true);

}

void ClientWindow::errorSocket(QAbstractSocket::SocketError error)
{
    switch(error)
    {
    case QAbstractSocket::HostNotFoundError:
        ui->display->append(tr("<em>ERROR: server could not be found.</em>"));
        break;
    case QAbstractSocket::ConnectionRefusedError:
        ui->display->append(tr("<em>ERROR: server refused connection. it may not be launched</em>"));
        break;
    case QAbstractSocket::RemoteHostClosedError:
        ui->display->append(tr("<em>ERROR: server stopped the connection</em>"));
        break;
    default:
        ui->display->append(tr("<em>ERROR: ") + socket->errorString() + tr("</em>"));
    }

    ui->connectButton->setEnabled(true);
}
